package com.cskaoyan.udp.edition1;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;

/*
       接收端:
        1.建立udp的socket对象.
            DatagramSocket： 此类表示用来发送和接收数据报包的套接字。

              // 套接字: ip + port
              DatagramSocket(int port)
                 创建数据报套接字并将其绑定到本地主机上的指定端口。

        2.创建用于接收数据的数据报包

        DatagramPacket(byte[] buf, int offset, int length)
          构造 DatagramPacket，用来接收长度为 length 的包，在缓冲区中指定了偏移量。
          参数：
            buf - 保存传入数据报的缓冲区。
            offset - 缓冲区的偏移量
            length - 读取的字节数。



        3.通过socket对象的receive方法接收数据

            public void receive(DatagramPacket p)
               1）从此套接字接收数据报包。
               2）当此方法返回时，DatagramPacket 的缓冲区填充了接收的数据
               3）此方法在接收到数据报前一直阻塞(阻塞)
               4）数据报包也包含发送方的 IP 地址和发送方机器上的端口号。

        4.可以对资源进行释放


                注意事项:
         1. DatagramSocket的receive方法是一个阻塞方法

         2. BindException: Address already in use: Cannot bind
            这里的address指的是套接字地址:  ip + port

            一个端口号表示一个进程的逻辑地址，一个端口号只能绑定一个进程
            但是，一个进程可以绑定多个端口号

 */
public class Receiver {

    public static void main(String[] args) throws IOException {
        // 传输层
        // 创建DatagramSocket
        DatagramSocket datagramSocket = new DatagramSocket(10087);

        //创建用于接收数据的数据报包
        byte[] bytes = new byte[1024];
        int off = 0;
        DatagramPacket receivePacket = new DatagramPacket(bytes, off, bytes.length);

        // 接收数据
        // receive方法是阻塞方法
        datagramSocket.receive(receivePacket);

        // 释放资源
        datagramSocket.close();

        // -------------------------------------------------------------------------------------
        // 应用层，解析接收到的数据
        // 获取数据报包中，存放接收数据的自己数组
        byte[] data = receivePacket.getData();
        // 获取接收到的数据，在字节数组中，存放的偏移量
        int offset = receivePacket.getOffset();
        // 获取实际接收到字节数据的个数
        int length = receivePacket.getLength();

        String result = new String(data, off, length);

        // 可以通过访问接收数据的数据报报，知道数据发送方的ip地址和端口号
        // 获取方法放ip地址
        InetAddress address = receivePacket.getAddress();
        // 获取方法方发送数据的端口
        int port = receivePacket.getPort();
        System.out.println(address + "-" + port+ ":" + result);

    }
}
